From 2b2d6bf747533c7175e3f9f2debca05495e99ade Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 12 Mar 2020 00:34:45 -0400 Subject: [PATCH] win32: implement subtypes --- gdk/win32/gdksurface-win32.c | 489 ++++++++++++++++++++++++++++++++++- 1 file changed, 483 insertions(+), 6 deletions(-) diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c index 3ad928deff..48f2182b38 100644 --- a/gdk/win32/gdksurface-win32.c +++ b/gdk/win32/gdksurface-win32.c @@ -123,6 +123,14 @@ static void gdk_win32_impl_frame_clock_after_paint (GdkFrameClock *clock, G_DEFINE_TYPE (GdkWin32Surface, gdk_win32_surface, GDK_TYPE_SURFACE) +GType gdk_win32_toplevel_get_type (void) G_GNUC_CONST; +GType gdk_win32_popup_get_type (void) G_GNUC_CONST; +GType gdk_win32_drag_surface_get_type (void) G_GNUC_CONST; + +#define GDK_TYPE_WIN32_TOPLEVEL (gdk_win32_toplevel_get_type ()) +#define GDK_TYPE_WIN32_POPUP (gdk_win32_popup_get_type ()) +#define GDK_TYPE_WIN32_DRAG_SURFACE (gdk_win32_drag_surface_get_type ()) + static void gdk_win32_surface_init (GdkWin32Surface *impl) { @@ -500,12 +508,31 @@ _gdk_win32_display_create_surface (GdkDisplay *display, else frame_clock = _gdk_frame_clock_idle_new (); - impl = g_object_new (GDK_TYPE_WIN32_SURFACE, - "surface-type", surface_type, - "display", display, - "parent", parent, - "frame-clock", frame_clock, - NULL); + switch (surface_type) + { + case GDK_SURFACE_TOPLEVEL: + impl = g_object_new (GDK_TYPE_WIN32_TOPLEVEL, + "display", display, + "frame-clock", frame_clock, + NULL); + break; + case GDK_SURFACE_POPUP: + impl = g_object_new (GDK_TYPE_WIN32_POPUP, + "parent", parent, + "display", display, + "frame-clock", frame_clock, + NULL); + break; + case GDK_SURFACE_TEMP: + impl = g_object_new (GDK_TYPE_WIN32_DRAG_SURFACE, + "display", display, + "frame-clock", frame_clock, + NULL); + break; + default: + g_assert_not_reached (); + break; + } surface = GDK_SURFACE (impl); surface->x = x; @@ -5085,3 +5112,453 @@ gdk_win32_surface_get_handle (GdkSurface *window) return GDK_SURFACE_HWND (window); } + +#define LAST_PROP 1 + +typedef struct +{ + GdkWin32Surface parent_instance; +} GdkWin32Popup; + +typedef struct +{ + GdkWin32SurfaceClass parent_class; +} GdkWin32PopupClass; + +static void gdk_win32_popup_iface_init (GdkPopupInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GdkWin32Popup, gdk_win32_popup, GDK_TYPE_WIN32_SURFACE, + G_IMPLEMENT_INTERFACE (GDK_TYPE_POPUP, + gdk_win32_popup_iface_init)) + +static void +gdk_win32_popup_init (GdkWin32Popup *popup) +{ +} + +static void +gdk_win32_popup_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GdkSurface *surface = GDK_SURFACE (object); + + switch (prop_id) + { + case LAST_PROP + GDK_POPUP_PROP_PARENT: + g_value_set_object (value, surface->parent); + break; + + case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE: + g_value_set_boolean (value, surface->autohide); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gdk_win32_popup_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GdkSurface *surface = GDK_SURFACE (object); + + switch (prop_id) + { + case LAST_PROP + GDK_POPUP_PROP_PARENT: + surface->parent = g_value_dup_object (value); + if (surface->parent != NULL) + surface->parent->children = g_list_prepend (surface->parent->children, surface); + break; + + case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE: + surface->autohide = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gdk_win32_popup_class_init (GdkWin32PopupClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->get_property = gdk_win32_popup_get_property; + object_class->set_property = gdk_win32_popup_set_property; + + gdk_popup_install_properties (object_class, 1); +} + +static gboolean +gdk_win32_popup_present (GdkPopup *popup, + int width, + int height, + GdkPopupLayout *layout) +{ + return gdk_win32_surface_present_popup (GDK_SURFACE (popup), width, height, layout); +} + +static GdkGravity +gdk_win32_popup_get_surface_anchor (GdkPopup *popup) +{ + return GDK_SURFACE (popup)->popup.surface_anchor; +} + +static GdkGravity +gdk_win32_popup_get_rect_anchor (GdkPopup *popup) +{ + return GDK_SURFACE (popup)->popup.rect_anchor; +} + +static int +gdk_win32_popup_get_position_x (GdkPopup *popup) +{ + return GDK_SURFACE (popup)->x; +} + +static int +gdk_win32_popup_get_position_y (GdkPopup *popup) +{ + return GDK_SURFACE (popup)->y; +} + +static void +gdk_win32_popup_iface_init (GdkPopupInterface *iface) +{ + iface->present = gdk_win32_popup_present; + iface->get_surface_anchor = gdk_win32_popup_get_surface_anchor; + iface->get_rect_anchor = gdk_win32_popup_get_rect_anchor; + iface->get_position_x = gdk_win32_popup_get_position_x; + iface->get_position_y = gdk_win32_popup_get_position_y; +} + + +typedef struct +{ + GdkWin32Surface parent_instance; +} GdkWin32Toplevel; + +typedef struct +{ + GdkWin32SurfaceClass parent_class; +} GdkWin32ToplevelClass; + +static void gdk_win32_toplevel_iface_init (GdkToplevelInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GdkWin32Toplevel, gdk_win32_toplevel, GDK_TYPE_WIN32_SURFACE, + G_IMPLEMENT_INTERFACE (GDK_TYPE_TOPLEVEL, + gdk_win32_toplevel_iface_init)) + +static void +gdk_win32_toplevel_init (GdkWin32Toplevel *toplevel) +{ +} + +static void +gdk_win32_toplevel_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GdkSurface *surface = GDK_SURFACE (object); + + switch (prop_id) + { + case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE: + gdk_win32_surface_set_title (surface, g_value_get_string (value)); + g_object_notify_by_pspec (G_OBJECT (surface), pspec); + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID: + gdk_win32_surface_set_startup_id (surface, g_value_get_string (value)); + g_object_notify_by_pspec (G_OBJECT (surface), pspec); + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR: + gdk_win32_surface_set_transient_for (surface, g_value_get_object (value)); + g_object_notify_by_pspec (G_OBJECT (surface), pspec); + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_STICKY: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_KEEP_ABOVE: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_KEEP_BELOW: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_ACCEPT_FOCUS: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_FOCUS_ON_MAP: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE: + surface->fullscreen_mode = g_value_get_enum (value); + g_object_notify_by_pspec (G_OBJECT (surface), pspec); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gdk_win32_toplevel_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GdkSurface *surface = GDK_SURFACE (object); + GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface); + + switch (prop_id) + { + case LAST_PROP + GDK_TOPLEVEL_PROP_STATE: + g_value_set_flags (value, surface->state); + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE: + g_value_set_string (value, impl->title); + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID: + g_value_set_string (value, ""); + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR: + g_value_set_object (value, impl->transient_for); + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST: + g_value_set_pointer (value, NULL); + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_STICKY: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_KEEP_ABOVE: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_KEEP_BELOW: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_KEEP_BELOW: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_ACCEPT_FOCUS: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_FOCUS_ON_MAP: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE: + break; + + case LAST_PROP + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE: + g_value_set_enum (value, surface->fullscreen_mode); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gdk_win32_toplevel_class_init (GdkWin32ToplevelClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->get_property = gdk_win32_toplevel_get_property; + object_class->set_property = gdk_win32_toplevel_set_property; + + gdk_toplevel_install_properties (object_class, 1); +} + +static void +show_surface (GdkSurface *surface) +{ + gboolean was_mapped; + + if (surface->destroyed) + return; + + was_mapped = GDK_SURFACE_IS_MAPPED (surface); + + if (!was_mapped) + gdk_synthesize_surface_state (surface, GDK_SURFACE_STATE_WITHDRAWN, 0); + + _gdk_surface_update_viewable (surface); + + gdk_win32_surface_show (surface, FALSE); + + if (!was_mapped) + { + if (gdk_surface_is_viewable (surface)) + gdk_surface_invalidate_rect (surface, NULL); + } +} + +static gboolean +gdk_win32_toplevel_present (GdkToplevel *toplevel, + int width, + int height, + GdkToplevelLayout *layout) +{ + GdkSurface *surface = GDK_SURFACE (toplevel); + GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface); + GdkGeometry geometry; + GdkSurfaceHints mask; + + if (gdk_toplevel_layout_get_resizable (layout)) + { + geometry.min_width = gdk_toplevel_layout_get_min_width (layout); + geometry.min_height = gdk_toplevel_layout_get_min_height (layout); + mask = GDK_HINT_MIN_SIZE; + } + else + { + geometry.max_width = geometry.min_width = width; + geometry.max_height = geometry.min_height = height; + mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE; + } + gdk_win32_surface_set_geometry_hints (surface, &geometry, mask); + gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height); + gdk_win32_surface_resize (surface, width, height, impl->scale); + + if (gdk_toplevel_layout_get_maximized (layout)) + gdk_win32_surface_maximize (surface); + else + gdk_win32_surface_unmaximize (surface); + + if (gdk_toplevel_layout_get_fullscreen (layout)) + { + GdkMonitor *monitor = gdk_toplevel_layout_get_fullscreen_monitor (layout); + if (monitor) + gdk_win32_surface_fullscreen_on_monitor (surface, monitor); + else + gdk_win32_surface_fullscreen (surface); + } + else + gdk_win32_surface_unfullscreen (surface); + + gdk_win32_surface_set_modal_hint (surface, gdk_toplevel_layout_get_modal (layout)); + + show_surface (surface); + + return TRUE; +} + +static gboolean +gdk_win32_toplevel_minimize (GdkToplevel *toplevel) +{ + gdk_win32_surface_minimize (GDK_SURFACE (toplevel)); + + return TRUE; +} + +static gboolean +gdk_win32_toplevel_lower (GdkToplevel *toplevel) +{ + return FALSE; +} + +static void +gdk_win32_toplevel_focus (GdkToplevel *toplevel, + guint32 timestamp) +{ + gdk_win32_surface_focus (GDK_SURFACE (toplevel), timestamp); +} + +static gboolean +gdk_win32_toplevel_show_window_menu (GdkToplevel *toplevel, + GdkEvent *event) +{ + return gdk_win32_surface_show_window_menu (GDK_SURFACE (toplevel), event); +} + +static gboolean +gdk_win32_toplevel_supports_edge_constraints (GdkToplevel *toplevel) +{ + return gdk_win32_surface_supports_edge_constraints (GDK_SURFACE (toplevel)); +} + +static void +gdk_win32_toplevel_iface_init (GdkToplevelInterface *iface) +{ + iface->present = gdk_win32_toplevel_present; + iface->minimize = gdk_win32_toplevel_minimize; + iface->lower = gdk_win32_toplevel_lower; + iface->focus = gdk_win32_toplevel_focus; + iface->show_window_menu = gdk_win32_toplevel_show_window_menu; + iface->supports_edge_constraints = gdk_win32_toplevel_supports_edge_constraints; +} + +typedef struct +{ + GdkWin32Surface parent_instance; +} GdkWin32DragSurface; + +typedef struct +{ + GdkWin32SurfaceClass parent_class; +} GdkWin32DragSurfaceClass; + +static void gdk_win32_drag_surface_iface_init (GdkDragSurfaceInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GdkWin32DragSurface, gdk_win32_drag_surface, GDK_TYPE_WIN32_SURFACE, + G_IMPLEMENT_INTERFACE (GDK_TYPE_DRAG_SURFACE, + gdk_win32_drag_surface_iface_init)) + +static void +gdk_win32_drag_surface_init (GdkWin32DragSurface *surface) +{ +} + +static void +gdk_win32_drag_surface_class_init (GdkWin32DragSurfaceClass *class) +{ +} + +static gboolean +gdk_win32_drag_surface_present (GdkDragSurface *drag_surface, + int width, + int height) +{ + GdkSurface *surface = GDK_SURFACE (drag_surface); + GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface); + + gdk_win32_surface_resize (surface, width, height, impl->scale); + show_surface (surface); + + return TRUE; +} + +static void +gdk_win32_drag_surface_iface_init (GdkDragSurfaceInterface *iface) +{ + iface->present = gdk_win32_drag_surface_present; +} -- 2.30.2